/**
 * @author 张慧华 z@j-ui.com
 *
 */

var DWZ = {
    version: '1.5.2',
    regPlugins: [], // [function($parent){} ...]
    // sbar: show sidebar
    keyCode: {
        ENTER: 13, ESC: 27, END: 35, HOME: 36,
        SHIFT: 16, TAB: 9,
        LEFT: 37, RIGHT: 39, UP: 38, DOWN: 40,
        DELETE: 46, BACKSPACE: 8
    },
    eventType: {
        pageClear: "pageClear",	// 用于重新ajaxLoad、关闭nabTab, 关闭dialog时，去除xheditor等需要特殊处理的资源
        resizeGrid: "resizeGrid"	// 用于窗口或dialog大小调整
    },
    isOverAxis: function (x, reference, size) {
        //Determines when x coordinate is over "b" element axis
        return (x > reference) && (x < (reference + size));
    },
    isOver: function (y, x, top, left, height, width) {
        //Determines when x, y coordinates is over "b" element
        return this.isOverAxis(y, top, height) && this.isOverAxis(x, left, width);
    },

    pageInfo: {
        pageNum: "pageNum",
        numPerPage: "numPerPage",
        orderField: "orderField",
        orderDirection: "orderDirection"
    },
    statusCode: {ok: 200, error: 300, timeout: 301},
    keys: {statusCode: "statusCode", message: "message"},
    ui: {
        sbar: true,
        hideMode: 'display' //navTab组件切换的隐藏方式，支持的值有’display’，’offsets’负数偏移位置的值，默认值为’display’
    },
    frag: {}, //page fragment
    _msg: {}, //alert message
    _set: {
        loginUrl: "", //session timeout
        loginTitle: "", //if loginTitle open a login dialog
        debug: false
    },
    msg: function (key, args) {
        var _format = function (str, args) {
            args = args || [];
            var result = str || "";
            for (var i = 0; i < args.length; i++) {
                result = result.replace(new RegExp("\\{" + i + "\\}", "g"), args[i]);
            }
            return result;
        }
        return _format(this._msg[key], args);
    },
    debug: function (msg) {
        if (this._set.debug) {
            if (typeof (console) != "undefined") console.log(msg);
            else alert(msg);
        }
    },
    loadLogin: function () {
        if ($.pdialog && DWZ._set.loginTitle) {
            $.pdialog.open(DWZ._set.loginUrl, "login", DWZ._set.loginTitle, {mask: true, width: 520, height: 260});
        } else {
            window.location = DWZ._set.loginUrl;
        }
    },

    /*
     * json to string
     */
    obj2str: function (o) {
        var r = [];
        if (typeof o == "string") return "\"" + o.replace(/([\'\"\\])/g, "\\$1").replace(/(\n)/g, "\\n").replace(/(\r)/g, "\\r").replace(/(\t)/g, "\\t") + "\"";
        if (typeof o == "object") {
            if (!o.sort) {
                for (var i in o)
                    r.push(i + ":" + DWZ.obj2str(o[i]));
                if (!!document.all && !/^\n?function\s*toString\(\)\s*\{\n?\s*\[native code\]\n?\s*\}\n?\s*$/.test(o.toString)) {
                    r.push("toString:" + o.toString.toString());
                }
                r = "{" + r.join() + "}"
            } else {
                for (var i = 0; i < o.length; i++) {
                    r.push(DWZ.obj2str(o[i]));
                }
                r = "[" + r.join() + "]"
            }
            return r;
        }
        return o.toString();
    },
    jsonEval: function (data) {
        try {
            if ($.type(data) == 'string')
                return eval('(' + data + ')');
            else return data;
        } catch (e) {
            return {};
        }
    },
    ajaxError: function (xhr, ajaxOptions, thrownError) {
        if (alertMsg) {
            alertMsg.error("<div>Http status: " + xhr.status + " " + xhr.statusText + "</div>"
                + "<div>ajaxOptions: " + ajaxOptions + "</div>"
                + "<div>thrownError: " + thrownError + "</div>"
                + "<div>" + xhr.responseText + "</div>");
        } else {
            alert("Http status: " + xhr.status + " " + xhr.statusText + "\najaxOptions: " + ajaxOptions + "\nthrownError:" + thrownError + "\n" + xhr.responseText);
        }
    },
    ajaxDone: function (json) {
        if (json[DWZ.keys.statusCode] == DWZ.statusCode.error) {
            if (json[DWZ.keys.message] && alertMsg) alertMsg.error(json[DWZ.keys.message]);
        } else if (json[DWZ.keys.statusCode] == DWZ.statusCode.timeout) {
            if (alertMsg) alertMsg.error(json[DWZ.keys.message] || DWZ.msg("sessionTimout"), {okCall: DWZ.loadLogin});
            else DWZ.loadLogin();
        } else if (json[DWZ.keys.statusCode] == DWZ.statusCode.ok) {
            if (json[DWZ.keys.message] && alertMsg) alertMsg.correct(json[DWZ.keys.message]);
        }
        ;
    },

    init: function (pageFrag, options) {
        var op = $.extend({
            loginUrl: "login.html", loginTitle: null, callback: null, debug: false,
            statusCode: {}, keys: {}
        }, options);
        this._set.loginUrl = op.loginUrl;
        this._set.loginTitle = op.loginTitle;
        this._set.debug = op.debug;
        $.extend(DWZ.statusCode, op.statusCode);
        $.extend(DWZ.keys, op.keys);
        $.extend(DWZ.pageInfo, op.pageInfo);
        $.extend(DWZ.ui, op.ui);

        jQuery.ajax({
            type: 'GET',
            url: pageFrag,
            dataType: 'xml',
            timeout: 50000,
            cache: false,
            error: function (xhr) {
                alert('Error loading XML document: ' + pageFrag + "\nHttp status: " + xhr.status + " " + xhr.statusText);
            },
            success: function (xml) {
                $(xml).find("_PAGE_").each(function () {
                    var pageId = $(this).attr("id");
                    if (pageId) DWZ.frag[pageId] = $(this).text();
                });

                $(xml).find("_MSG_").each(function () {
                    var id = $(this).attr("id");
                    if (id) DWZ._msg[id] = $(this).text();
                });

                if (jQuery.isFunction(op.callback)) op.callback();
            }
        });

        var _doc = $(document);
        if (!_doc.isBind(DWZ.eventType.pageClear)) {
            _doc.bind(DWZ.eventType.pageClear, function (event) {
                var box = event.target;
                if ($.fn.xheditor) {
                    $("textarea.editor", box).xheditor(false);
                }
            });
        }
    }
};


(function ($) {
    // DWZ set regional
    $.setRegional = function (key, value) {
        if (!$.regional) $.regional = {};
        $.regional[key] = value;
    };

    $.fn.extend({
        /**
         * @param {Object} op: {type:GET/POST, url:ajax请求地址, data:ajax请求参数列表, callback:回调函数 }
         */
        ajaxUrl: function (op) {
            var $this = $(this);

            $this.trigger(DWZ.eventType.pageClear);

            $.ajax({
                type: op.type || 'GET',
                url: op.url,
                data: op.data,
                cache: false,
                success: function (response) {
                    var json = DWZ.jsonEval(response);

                    if (json[DWZ.keys.statusCode] == DWZ.statusCode.error) {
                        if (json[DWZ.keys.message]) alertMsg.error(json[DWZ.keys.message]);
                    } else {
                        $this.html(response).initUI();
                        if ($.isFunction(op.callback)) op.callback(response);
                    }

                    if (json[DWZ.keys.statusCode] == DWZ.statusCode.timeout) {
                        if ($.pdialog) $.pdialog.checkTimeout();
                        if (navTab) navTab.checkTimeout();

                        alertMsg.error(json[DWZ.keys.message] || DWZ.msg("sessionTimout"), {
                            okCall: function () {
                                DWZ.loadLogin();
                            }
                        });
                    }

                },
                error: DWZ.ajaxError,
                statusCode: {
                    503: function (xhr, ajaxOptions, thrownError) {
                        alert(DWZ.msg("statusCode_503") || thrownError);
                    }
                }
            });
        },
        loadUrl: function (url, data, callback) {
            $(this).ajaxUrl({url: url, data: data, callback: callback});
        },

        initUI: function () {
            return this.each(function () {
                var $this = $(this);
                $.each(DWZ.regPlugins, function (index, fn) {
                    fn($this);
                });
            });
        },
        /**
         * adjust component inner reference box height
         * @param {Object} refBox: reference box jQuery Obj
         */
        layoutH: function ($refBox) {
            return this.each(function () {
                var $this = $(this);
                if (!$refBox) $refBox = $this.parents("div.layoutBox:first");
                var iRefH = $refBox.height();
                var iLayoutH = parseInt($this.attr("layoutH"));
                var iH = iRefH - iLayoutH > 50 ? iRefH - iLayoutH : 50;

                if ($this.isTag("table")) {
                    $this.removeAttr("layoutH").wrap('<div layoutH="' + iLayoutH + '" style="overflow:auto;height:' + iH + 'px"></div>');
                } else {
                    $this.height(iH).css("overflow", "auto");
                }
            });
        },
        hoverClass: function (className, speed) {
            var _className = className || "hover";
            return this.each(function () {
                var $this = $(this), mouseOutTimer;
                $this.hover(function () {
                    if (mouseOutTimer) clearTimeout(mouseOutTimer);
                    $this.addClass(_className);
                }, function () {
                    mouseOutTimer = setTimeout(function () {
                        $this.removeClass(_className);
                    }, speed || 10);
                });
            });
        },
        focusClass: function (className) {
            var _className = className || "textInputFocus";
            return this.each(function () {
                $(this).focus(function () {
                    $(this).addClass(_className);
                }).blur(function () {
                    $(this).removeClass(_className);
                });
            });
        },
        inputAlert: function () {
            return this.each(function () {

                var $this = $(this);

                function getAltBox() {
                    return $this.parent().find("label.alt");
                }

                function altBoxCss(opacity) {
                    var position = $this.position();
                    return {
                        width: $this.width(),
                        top: position.top + 'px',
                        left: position.left + 'px',
                        opacity: opacity || 1
                    };
                }

                if (getAltBox().size() < 1) {
                    if (!$this.attr("id")) $this.attr("id", $this.attr("name") + "_" + Math.round(Math.random() * 10000));
                    var $label = $('<label class="alt" for="' + $this.attr("id") + '">' + $this.attr("alt") + '</label>').appendTo($this.parent());

                    $label.css(altBoxCss(1));
                    if ($this.val()) $label.hide();
                }

                $this.focus(function () {
                    getAltBox().css(altBoxCss(0.3));
                }).blur(function () {
                    if (!$(this).val()) getAltBox().show().css("opacity", 1);
                }).keydown(function () {
                    getAltBox().hide();
                });
            });
        },
        isTag: function (tn) {
            if (!tn) return false;
            return $(this)[0].tagName.toLowerCase() == tn ? true : false;
        },
        /**
         * 判断当前元素是否已经绑定某个事件
         * @param {Object} type
         */
        isBind: function (type) {
            var _events = $(this).data("events");
            return _events && type && _events[type];
        },
        /**
         * 输出firebug日志
         * @param {Object} msg
         */
        log: function (msg) {
            return this.each(function () {
                if (console) console.log("%s: %o", msg, this);
            });
        }
    });

    /**
     * 扩展String方法
     */
    $.extend(String.prototype, {
        isPositiveInteger: function () {
            return (new RegExp(/^[1-9]\d*$/).test(this));
        },
        isInteger: function () {
            return (new RegExp(/^\d+$/).test(this));
        },
        isNumber: function (value, element) {
            return (new RegExp(/^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/).test(this));
        },
        trim: function () {
            return this.replace(/(^\s*)|(\s*$)|\r|\n/g, "");
        },
        startsWith: function (pattern) {
            return this.indexOf(pattern) === 0;
        },
        endsWith: function (pattern) {
            var d = this.length - pattern.length;
            return d >= 0 && this.lastIndexOf(pattern) === d;
        },
        replaceSuffix: function (index) {
            return this.replace(/\[[0-9]+\]/, '[' + index + ']').replace('#index#', index);
        },
        trans: function () {
            return this.replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&quot;/g, '"');
        },
        encodeTXT: function () {
            return (this).replaceAll('&', '&amp;').replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll(" ", "&nbsp;");
        },
        replaceAll: function (os, ns) {
            return this.replace(new RegExp(os, "gm"), ns);
        },
        replaceTm: function ($data) {
            if (!$data) return this;
            return this.replace(RegExp("({[A-Za-z_]+[A-Za-z0-9_]*})", "g"), function ($1) {
                return $data[$1.replace(/[{}]+/g, "")];
            });
        },
        replaceTmById: function (_box) {
            var $parent = _box || $(document);
            return this.replace(RegExp("({[A-Za-z_]+[A-Za-z0-9_]*})", "g"), function ($1) {
                var $input = $parent.find("#" + $1.replace(/[{}]+/g, ""));
                return $input.val() ? $input.val() : $1;
            });
        },
        isFinishedTm: function () {
            return !(new RegExp("{[A-Za-z_]+[A-Za-z0-9_]*}").test(this));
        },
        skipChar: function (ch) {
            if (!this || this.length === 0) {
                return '';
            }
            if (this.charAt(0) === ch) {
                return this.substring(1).skipChar(ch);
            }
            return this;
        },
        isValidPwd: function () {
            return (new RegExp(/^([_]|[a-zA-Z0-9]){6,32}$/).test(this));
        },
        isValidMail: function () {
            return (new RegExp(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/).test(this.trim()));
        },
        isSpaces: function () {
            for (var i = 0; i < this.length; i += 1) {
                var ch = this.charAt(i);
                if (ch != ' ' && ch != "\n" && ch != "\t" && ch != "\r") {
                    return false;
                }
            }
            return true;
        },
        isPhone: function () {
            return (new RegExp(/(^([0-9]{3,4}[-])?\d{3,8}(-\d{1,6})?$)|(^\([0-9]{3,4}\)\d{3,8}(\(\d{1,6}\))?$)|(^\d{3,8}$)/).test(this));
        },
        isUrl: function () {
            return (new RegExp(/^[a-zA-z]+:\/\/([a-zA-Z0-9\-\.]+)([-\w .\/?%&=:]*)$/).test(this));
        },
        isExternalUrl: function () {
            return this.isUrl() && this.indexOf("://" + document.domain) == -1;
        }
    });
})(jQuery);

/**
 * You can use this map like this:
 * var myMap = new Map();
 * myMap.put("key","value");
 * var key = myMap.get("key");
 * myMap.remove("key");
 */
function Map() {

    this.elements = new Array();

    this.size = function () {
        return this.elements.length;
    }

    this.isEmpty = function () {
        return (this.elements.length < 1);
    }

    this.clear = function () {
        this.elements = new Array();
    }

    this.put = function (_key, _value) {
        this.remove(_key);
        this.elements.push({key: _key, value: _value});
    }

    this.remove = function (_key) {
        try {
            for (i = 0; i < this.elements.length; i++) {
                if (this.elements[i].key == _key) {
                    this.elements.splice(i, 1);
                    return true;
                }
            }
        } catch (e) {
            return false;
        }
        return false;
    }

    this.get = function (_key) {
        try {
            for (i = 0; i < this.elements.length; i++) {
                if (this.elements[i].key == _key) {
                    return this.elements[i].value;
                }
            }
        } catch (e) {
            return null;
        }
    }

    this.element = function (_index) {
        if (_index < 0 || _index >= this.elements.length) {
            return null;
        }
        return this.elements[_index];
    }

    this.containsKey = function (_key) {
        try {
            for (i = 0; i < this.elements.length; i++) {
                if (this.elements[i].key == _key) {
                    return true;
                }
            }
        } catch (e) {
            return false;
        }
        return false;
    }

    this.values = function () {
        var arr = new Array();
        for (i = 0; i < this.elements.length; i++) {
            arr.push(this.elements[i].value);
        }
        return arr;
    }

    this.keys = function () {
        var arr = new Array();
        for (i = 0; i < this.elements.length; i++) {
            arr.push(this.elements[i].key);
        }
        return arr;
    }
}
